iT邦幫忙

2022 iThome 鐵人賽

DAY 13
0
Modern Web

擁抱 .Net Core系列 第 13

[Day13] 選項模式 - Configuration - 4

  • 分享至 

  • xImage
  •  

昨天有提到我們在使用Config的時候,可以透過將設定綁定到POCO物件上的方式做使用
然後註冊該物件,並直接注入該物件做使用

但是如果是直接入物件的話,使用該Config的Service某種程度就會直接依賴該POCO
所以這時候應該透過介面來隔離他們,因此有了選項模式IOption<T>

IOption<T>

我們繼續用之前的appsettings.json 作為範例

{
  "line": {
    "channelId": "line_channel_id",
    "channelSecret": "line_channel_secret",
    "info": {
      "name": "line_bot_name",
      "pictureUrl": "line_bot_picture_url"
    }
  },
  "facebook": {
    "pageId": "facebook_page_id",
    "accessToken": "facebook_page_access_token",
    "appSecret": "facebook_app_secret"
  },
  "telegram": {
    "botToken": "telegram_bot_token"
  }
}

Program.cs

var settingFile = @"appsettings.json";
IConfiguration configuration = new ConfigurationBuilder()
    .AddJsonFile(settingFile)
    .Build();


var serviceProvider = new ServiceCollection()
    .AddOptions()
    .Configure<LineSetting>(configuration.GetSection("Line"))
    .BuildServiceProvider();

var option = serviceProvider.GetService<IOptions<LineSetting>>();

Console.WriteLine(option.Value.ChannelId);

可以看見在上方我用了AddOption()的擴充方法去註冊選項模式所需的物件,因為是Console,WebSdk的Host中本身已有這段所以不用特別加

然後再透過 Configure<T> 方法去將對應的IConfiguration綁定到選項上

在Service中則可以這樣注入使用

public class LineService
{
    private readonly IOptions<LineSetting> _lineSetting;

    public LineService(IOptions<LineSetting> lineSetting)
    {
        _lineSetting = lineSetting;
    }

    public void PrintLineAppName()
    {
        Console.WriteLine(_lineSetting.Value.Info.Name);
    }
}
  • IOption<T> 不支援 當設定更改的時候,變更其enitity的值
  • 本身的LifeTime是Singleton的,所以可以在任何服務中使用

IOptionSnapshot<T>

在每次請求或注入IOptionSnapshot\<T> 的時候,
會去讀取一次當前ScopeIConfiguration
已就是說,他是可以監控設定的變化的IOption<T>
註冊的方式一樣用 Configure就行

var serviceProvider = new ServiceCollection()
    .AddOptions()
    .Configure<LineSetting>(configuration.GetSection("Line"))
    .BuildServiceProvider();

但注入的時候型別使用IOptionSnapshot\<T>

public class LineService
{
    private readonly IOptionsSnapshot<LineSetting> _lineSetting;

    public LineService(IOptionsSnapshot<LineSetting> lineSetting)
    {
        _lineSetting = lineSetting;
    }

    public void PrintLineAppName()
    {
        Console.WriteLine(_lineSetting.Value.Info.Name);
    }
}

IOptionMonitor<T>

IOptionSnapshot 一樣,可以根據檔案的變化重新bind Entity
使用方式也很像
Program.cs

var serviceProvider = new ServiceCollection()
    .AddOptions()
    .Configure<LineSetting>(configuration.GetSection("Line"))
    .BuildServiceProvider();

注入的時候型別使用IOptionsMonitor\<T>
且讀取Option的時候使用的是 CurrentValue

public class LineService
{
    private readonly IOptionsMonitor<LineSetting> _lineSetting;

    public LineService(IOptionsMonitor<LineSetting> lineSetting)
    {
        _lineSetting = lineSetting;
    }

    public void PrintLineAppName()
    {
        Console.WriteLine(_lineSetting.CurrentValue.Info.Name);
    }
}

IOptionSnapshot<T>IOptionMonitor\<T> 主要差異在IOptionMonitor 的Lifetime被註冊為SingletonIOptionSnapshot則是Scoped

另外
IOptionMonitor\<T>還提供了一個方法OnChange(Action<TOptions, string> listener)
可以在設定檔變更時候自訂要觸發的事件。


上一篇
[Day12] 綁定物件以及常見的CoufigurationSource - Configuration - 3
下一篇
[Day14] 選項模式(2) - Configuration - 5
系列文
擁抱 .Net Core30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言